package com.saret.dictionary;

import com.google.inject.Inject;
import com.saret.crawler.search.DownloadPage;
import com.saret.crawler.search.SmartWebSearch;
import com.saret.crawler.search.WebTranslate;
import com.saret.crawler.type.GUrl;
import com.saret.utils.FileLocator;
import com.saret.utils.StringUtils;
import com.saret.utils.UtfFileHandle;

import java.io.File;
import java.util.*;
import java.util.logging.Logger;

/**
 * @author biniam.gebremichael
 * @since 12/27/11
 */
public class Dictionary {

    static int i = 0;

    private static final Logger logger = Logger.getLogger(Dictionary.class.getName());
    private static File enNlDic = new File(FileLocator.getTranslateDir(), "EN2NL.csv");

    private static Map<String, List<String>> enNl = UtfFileHandle.readDictionary(enNlDic, ",", ";");

    private SaveResult saveResult;
    private WebTranslate bingWebSearch;
    private DownloadPage downloadPage;
    private List<SourceSite> sourceUrl = new ArrayList<SourceSite>();

    @Inject
    public Dictionary(SmartWebSearch webSearch, DownloadPage downloadPage) {
        this.bingWebSearch = webSearch;
        this.downloadPage = downloadPage;
        sourceUrl.add(new SourceSite("europa.eu", "NL", "EN"));
        //   sourceUrl.add(new SourceSite("europa.eu", "NL", "EN"));
        //   sourceUrl.add(new SourceSite("electrolux-ui.com", "NL", "EN"));
        //  sourceUrl.add(new SourceSite("www.ind.nl", "english.", "www."));
    }

    public void getResult(String key) {
        saveResult = new SaveResult();
        for (SourceSite sourceSite : sourceUrl) {
            doSearch(key, sourceSite);
            saveResult.save(new File(FileLocator.getWorkingDir(), key.replaceAll("\\s+", "_") + ".xml"));
        }
    }

    public Set<GUrl> search(List<String> keys, SourceSite sourceSite) {
        final Set<GUrl> searchUrl = new TreeSet<GUrl>();
        for (String key : keys) {
            List<GUrl> search = bingWebSearch.search(sourceSite.searchKey(key));
            searchUrl.addAll(search);
        }
        return searchUrl;
    }

    public void doSearch(String en, SourceSite sourceSite) {
        List<String> nl = enNl.get(en);
        if (nl == null) {
            System.out.println(en + " does not exist in the dictionary");
            return;
        }
        saveResult.addWord(en, nl);
        System.out.println(String.format("looking for translation examples for \n\t(EN)%s -> (NL) %s in %s", en, nl.toString(), sourceSite.domain));
        Set<GUrl> search = search(nl, sourceSite);
        download(en, sourceSite, search);
    }


    private void download(String key, SourceSite sourceSite, Collection<GUrl> search) {
        for (GUrl nlUrl : search) {
            if (sourceSite.validForward(nlUrl.getUrl())) {
                String enUrl = sourceSite.translate(nlUrl.getUrl());
                File enFile = downloadPage.download(enUrl, nlUrl.hashCode() + "LANGUAGE-1", nlUrl.getType());
                for (String s : normalize3(enFile)) {
                    if (s != null && s.contains(key)) {
                        File nlFile = downloadPage.download(nlUrl.getUrl(), nlUrl.hashCode() + "LANGUAGE-2", nlUrl.getType());
                        getMatchingLines(key, enFile, enUrl, nlFile, nlUrl.getUrl());
                        break;
                    }
                }
            }
        }
    }

    public void getMatchingLines(String key, File enFile, String enUrl, File nlFile, String nlUrl) {
        String enLine = getMatchingLine(key, enFile);

        String nlBingTranslated = bingWebSearch.translate("EN", "NL", enLine);
        String nlLine = "";
        double score = 0;

        List<String> nl = enNl.get(key);
        for (String s : normalize(nlFile)) {
            for (String s1 : nl) {
                if (s != null && s.contains(s1)) {
                    double myScore = Score.score(s, Arrays.asList(nlBingTranslated.split("\\s+")));
                    if (score < myScore) {
                        nlLine = s;
                        score = myScore;
                    }
                    break;
                }
            }
        }

        if (enLine.length() > 1 && nlLine.length() > 1 && score > 0.05) {
            saveResult.addExample(enLine, enUrl, nlLine, nlUrl, score);
            logger.info(String.format("En %d %s\n", i++, enLine));
            logger.info(String.format("Nl (%.2f) %s\n", score, nlLine));
        }
    }

     private List<String> normalize3(File f){
       return UtfFileHandle.readFileToListOfLines(f);
     }
    private List<String> normalize(File f){
        List<String> lines = new ArrayList<String>();
        for (String s : UtfFileHandle.readFileToListOfLines(f)) {
            String[] words = s.split("\\s+");
            StringBuilder builder=new StringBuilder();
            for (String word : words) {
               boolean valid = StringUtils.match(word.trim(),"^[<|>]",0)==null;
                if(valid && word.length()<25)
                  builder.append(word).append(" ");
            }
            builder.append("\n");
            lines.add(builder.toString());
        }
       return lines;
    }

    private String getMatchingLine(String key, File enFile) {
        String enLine = "";
        for (String s : normalize(enFile)) {
            if (s != null && s.contains(key)) {
                enLine = s;
                break;
            }
        }
        return enLine;
    }

    public Collection<String> miniDic(String enLine) {
        String[] words = enLine.replace("['|-]", " ").split("\\s+");
        Set<String> nlWords = new TreeSet<String>();
        for (String word : words) {
            if (word.length() > 2) {
                List<String> nl = enNl.get(word);
                if (nl != null) {
                    nlWords.addAll(nl);
                }
            }
        }
        return nlWords;
    }



}
